﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Swift;
using Utils;

namespace TB {
    public class Actor : ICloneable{

        public static Timer Timer;
        public string UID;
        int tid;

        public int TID {
            set {
                tid = value;
            }
            get {
                return tid + Blood;
            }
        }

        /// <summary>
        /// 表示该 Actor 在客户端是否存在
        /// </summary>
        public bool Alive = false;
        
        public float Size;

        /// <summary>
        /// 标签，辅助说明该 Actor 类型
        /// </summary>
        public string Tag;

        #region 位置
        float x;
        float y;

        public int X {
            set {
                CoordinateUtil.IntToFloatX (value, out x, Size);          
            }
        }

        public int Y {
            set {
                CoordinateUtil.IntToFloatY (value, out y, Size);       
            }
        }

        public float GetX() {  // 中心点
            return x;
        }

        public float GetY() {
            return y;
        }

        public float GetSX() {  // 左下角点
            return x - Size / 2;
        }

        public float GetSY() {
            return y - Size / 2;
        }

        public void SetX(float x) {
            this.x = x;
        }

        public void SetY(float y) {
            this.y = y;
        }
        #endregion

        #region 子弹专用
        public Actor Owner;
        #endregion

        #region 木墙专用

        public Actor UDActor;
        public Actor LRActor;

        public Actor GetImplicativeActor(DIR dir) {
            if(dir == DIR.UP || dir == DIR.DOWN)
                return UDActor;
            else
                return LRActor;
        }

        #endregion

        #region 坦克专用

        #region 玩家专用

        public int Life = 3;

        public void Adjust() {
            if(Tag.StartsWith("player")) {
                if(Blood == 1) {
                    Speed = 10;
                    BulletSpeed = 6;
                    ATK = 1;
                    CD = 1f;
                } else if(Blood == 2) {
                    Speed = 6;
                    BulletSpeed = 3;
                    ATK = 1;
                    CD = 0.5f;
                } else if(Blood == 3) {
                    Speed = 6;
                    BulletSpeed = 3;
                    ATK = 2;
                    CD = 0.5f;
                }
            }
        }

        #endregion

        

        public DIR Dir;
        public int Speed = 6;
        public int BulletSpeed = 6;
        public int ATK = 1;
        
        /// <summary>
        /// 攻击冷却时间，单位：秒
        /// </summary>
        public float CD = 2;
        bool cooling = true;
        public bool Cooling {
            get { return cooling; }
            set {
                if(value == true) {
                    throw new Exception ("Actor 的 cooling 属性不能手动设置成 true");
                }
                cooling = false;

                // 冷却时间
                if(CD > 0) {
                    Console.WriteLine ("冷却 CD " + CD + " , " + CD * 1000 );
                    // 在这找错一个小时。。。原本是 (long)(TimeUtils.Now + CD * 1000)。。。因为CD 是float， 所以内部先解析成float，先炸了。。
                    Timer.AddEvent ("Cooling_" + this.GetHashCode (), TimeUtils.Now + (long)(CD * 1000), 0, (name) => {
                        Console.WriteLine ("冷却结束");
                        cooling = true;
                    });
                } else {
                    cooling = true;
                }
            }
        }

        /// <summary>
        /// 攻击时，子弹出现的位置
        /// </summary>
        public float AX {
            get {
                if(Dir == DIR.LEFT || Dir == DIR.RIGHT) {
                    return x;
                } else if(Dir == DIR.UP) {
                    return x + Size / 2;
                } else {
                    return x - Size / 2;
                }
            }
        }

        public float AY {
            get {
                if(Dir == DIR.UP || Dir == DIR.DOWN) {
                    return y;
                } else if(Dir == DIR.LEFT) {
                    return y - Size / 2;
                } else {
                    return y + Size / 2;
                }
            }
        }

        public string AI;

        int blood = 0;
        public int Blood {
            get {
                return blood;
            }
            set {
                blood = value;
                Adjust ();
            }
        }

        public void Move(float dis) {
            switch(Dir) {
                case DIR.UP:
                    x += dis;
                    break;
                case DIR.DOWN:
                    x -= dis;
                    break;
                case DIR.LEFT:
                    y -= dis;
                    break;
                case DIR.RIGHT:
                    y += dis;
                    break;
            }
        }

        /// <summary>
        /// 坦克状态，解析成二进制，需要传递给客户端，客户端通过这个状态来做表现
        /// 第一位：是否暂停
        /// 第二位：是否无敌
        /// 第三位：是否打滑
        /// 第四位：是否正在移动
        /// 第五位：是否携带食物
        /// </summary>
        int status = 0;

        public int Status {
            get {
                return status;
            }
        }

        public bool WithFood {
            get {
                return (status & 16) > 0;
            }
            set {
                if(value == true) {
                    status |= 16;
                } else {
                    status |= 16;
                    status ^= 16;
                }
            }
        }

        public bool Paused {
            get {
                return (status & 1) > 0; 
            }
            set {
                if(value == true) {
                    status |= 1;
                } else {
                    status |= 1;
                    status ^= 1;
                }
            }
        }

        public bool CanKill {
            get {
                return (status & 2) == 0;
            }
            set {
                if(value == true) {
                    status |= 2;
                    status ^= 2;
                } else {
                    status |= 2;
                }
            }
        }

        public bool Slide {
            get {
                return (status & 4) > 0;
            }
            set {
                if(value == true) {
                    status |= 4;
                } else {
                    status |= 4;
                    status ^= 4;
                }
            }
        }

        public bool Moving {
            get {
                return (status & 8) > 0;
            }
            set {
                if(value == true) {
                    status |= 8;
                } else {
                    status |= 8;
                    status ^= 8;
                }
            }
        }

        #endregion

        #region 食物专用

        public int Type;    // 食物类型
        public int T = 15;  // 存在时间

        #endregion

        public object Clone() {
            return this.MemberwiseClone ();
        } 
    }
}
